#ifndef _CPP_HEADER_CODE_GENERATOR_H_
#define _CPP_HEADER_CODE_GENERATOR_H_

#include "CodeGenerator.h"

struct CppHeaderGenerator {
	xml_node m_Types;
	fstream  m_OutputStream;

	CppHeaderGenerator(xml_node types)
		:m_Types(types) 
	{}

	int Initial(const char* outfilepath);
	int Generate();
	int Finalize();
};


inline int CppHeaderGenerator::Initial(const char* typefilepath)
{
	char outfilepath[MAX_OUTPUT_PATH_LEN] = "";
	strcpy( outfilepath, typefilepath );
	char* ptr = strrchr(outfilepath, '.');
	strcpy(ptr, ".h");

	m_OutputStream.open(outfilepath, fstream::out);
    return 0;
}

inline int CppHeaderGenerator::Finalize()
{
	m_OutputStream.close();
	return 0;
}

inline int CppHeaderGenerator::Generate()
{
	/**
	* generate header file
	*/
	for( xml_node type = m_Types.first_child(); type; type=type.next_sibling() )
	{
		const char* type_name = type.attribute("type").value();
		/**
		* enum
		*/
		if( 0==strcmp(type_name, "enum") ) {
			m_OutputStream << "enum " << type.name() << " {\n";
			for(xml_node item=type.first_child(); item; item=item.next_sibling() )
			{
				m_OutputStream << "    " << item.name();
				if( item.attribute("value") ) {
					m_OutputStream << " = " << item.attribute("value").value();
				}
				m_OutputStream << (item.next_sibling()? ",\n" : "\n");
			}
			m_OutputStream << "};\n\n";
		} else 
        /**
		* struct
		*/
		if( 0==strcmp(type_name, "struct") ) {			
			m_OutputStream << "struct " << type.name() << " {\n";
			for(xml_node item=type.first_child(); item; item=item.next_sibling() )
			{	
				m_OutputStream << "    " << item.attribute("type").value() << " " << item.name() << ";\n";
			}
			m_OutputStream << "};\n\n";
		} else 
		/**
		* class
		*/
		if( 0==strcmp(type_name, "class") ) {
			m_OutputStream << "class " << type.name();
			if( type.attribute("super") ) 
				m_OutputStream << " : public " << type.attribute("super").value();
			m_OutputStream << " {\npublic:\n";
			for(xml_node item=type.first_child(); item; item=item.next_sibling() )
			{	
				if( 0!=strcmp(item.attribute("type").value(), "function") ) 
				    m_OutputStream << "    " << item.attribute("type").value() << " " << item.name() << ";\n";
			}
			m_OutputStream << "};\n\n";

		} else
		/**
		* runtime class
		*/
		if( 0==strcmp(type_name, "rtclass") ) {
			m_OutputStream << "class " << type.name();
			if( type.attribute("super") ) 
				m_OutputStream << " : public " << type.attribute("super").value();
			else
				m_OutputStream << " : public Object";
			m_OutputStream << " {\npublic:\n";
			for(xml_node item=type.first_child(); item; item=item.next_sibling() )
			{	
				if( 0!=strcmp(item.attribute("type").value(), "function") ) 
				    m_OutputStream << "    " << item.attribute("type").value() << " " << item.name() << ";\n";
			}
			m_OutputStream << "};\n\n";

		} else
		/**
		* basic type
		*/
		{
			if( 0!=strcmp(type.name(), type.attribute("type").value()) ) //define on for redefinition
			    m_OutputStream << "#define " << type.name() << " " << type.attribute("type").value() << "\n\n";
		}
	}
    return 0;
}


#endif //_CPP_HEADER_CODE_GENERATOR_H_
